#pragma once
#ifndef __VTEXTUREATLAS_H__
#define __VTEXTUREATLAS_H__

class VCoreApi VTextureAtlas
{
public:
	VTextureAtlas(UINT InitWidth, UINT InitHeight, UINT MaxWidth, UINT MaxHeight, BOOL PowerOfTwo = FALSE);
	~VTextureAtlas(void);
	BOOL AddElement(UINT& OffsetX, UINT& OffsetY, UINT Width, UINT Height);
	BOOL RemoveElement(UINT OffsetX, UINT OffsetY, UINT Width, UINT Height);
	void Clear(UINT MaxWidth, UINT MaxHeight);
	inline UINT GetWidth() const { return m_Width; }
	inline UINT GetHeight() const { return m_Height; }
private:
	int TryAddChildNode(int NodeIndex, UINT Width, UINT Height, BOOL bAllowTextureEnlargement);
	/** Recursively removes the children of a given node from the Nodes array and adjusts existing indices to compensate. */
	void RemoveChildNode(INT NodeIndex);
	

	inline int FindParentNode(int ChildNode) const
	{
		//@todo - could be a constant time search if the nodes stored a parent index
		for (INT NodeIndex = 0; NodeIndex < Nodes.Num(); NodeIndex++)
		{
			FTextureLayoutNode&	Node = Nodes(NodeIndex);
			if (Node.ChildA == SearchNodeIndex || Node.ChildB == SearchNodeIndex)
			{
				return NodeIndex;
			}
		}
		return INDEX_NONE;
	}

	struct AtlasNode
	{
		AtlasNode* Parent;
		AtlasNode* ChildA;
		AtlasNode* ChildB;
		WORD	OffsetX;
		WORD	OffsetY;
		WORD	Width;
		WORD	Height;
		BOOL	bUsed;

		inline AtlasNode() {}
		inline AtlasNode(AtlasNode* _Parent, WORD _OffsetX, WORD _OffsetY, WORD _Width, WORD _Height):
			Parent(_Parent),
			ChildA(NULL),
			ChildB(NULL),
			OffsetX(_OffsetX),
			OffsetY(_OffsetY),
			Width(_Width),
			Height(_Height),
			bUsed(FALSE)
		{}
	};

	UINT m_Width;
	UINT m_Height;
	BOOL m_PowOfTwo;
	VArray<AtlasNode> m_Nodes;
};

#endif 
